package com.kaigejava.queue;

/**
 * @author kaigejava
 * 队列对象
 * 一个队列必有元素
 * 1：队列能存放的最大值
 * 2：队列头指针
 * 3：队列为指针
 * 4：存放队列的容器--这里使用数组
 * 约定：
 * 当front = rear == -1的时候表示当前队列是空队列
 * 其中 front = -1;表示头指针指向队列头的前一个位置
 * rear = -1; 指向队列尾部。是尾部的数据，既是队列中最后一个数据
 * 模拟队列的功能：
 * 1：向队列中添加数据；
 * 2：从队列中获取数据
 * 3：队列是否为空
 * 4：队列是否已经满了
 * 5：显示队列头数据
 */
public class ArrayQueue {
    /**
     * 队列的最大值
     */
    private int maxSize;

    /**
     * 队列头
     */
    private int front;

    /**
     * 对列尾部
     */
    private  int rear;

    /**
     * 存放数据的容器
     */
    private int [] arr;

    /**
     * 初始化队列
     * @param maxSize
     */
    public ArrayQueue(int maxSize){
        this.maxSize = maxSize;
        this.arr = new int[maxSize];
        this.front = -1;
        this.rear = -1;
    }

    /**
     * 判断队列是否已经满了。
     * 队列满的标记就是 rear = maxSize-1的时候
     * @return
     */
    public boolean isFull(){
        return rear == maxSize -1;
    }

    /**
     * 判断队列是否为空
     * 判断依据：当rear = front 的时候。
     * @return
     */
    public boolean isEmpty(){
        return  rear == front;
    }

    /**
     * 加入队列
     * 思路：
     *  加入队列，尾指针++.当为空的时候，不能继续添加了。
     *  被加入的数据的下标等于rear指针后移后的位置
     * @param n
     */
    public  void addQueue(int n){
        if(isFull()){
            System.out.println("队列已经满了。不能继续添加了");
            return;
        }
        //尾指针向后移动。因为real从-1开始的
        rear ++ ;
        arr[rear] = n;
    }

    /**
     * 取数据
     * 思路：
     * 取数据的时候，是从头开始的。所以头指针要++。需要判读是否为空。为空的话，不能在取数据了
     * 当为空的话，抛出异常。不能-1.因为-1有意义
     * @return
     */
    public int getQueue(){
        if(isEmpty()){
            System.out.println("队列为空。不能继续获取到数据了");
            throw  new RuntimeException("队列为空");
        }
        front ++;
        return arr[front];
    }

    /**
     * 查看队列中所有数据
     */
    public void  showAll(){
        if(isEmpty()){
            System.out.printf("队列为空。不能继续获取到数据了");
            throw  new RuntimeException("队列为空");
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr[%d] = %d \n ",i,arr[i]);
        }
    }

    /**
     * 显示队列头数据。
     * 注意：不是获取。只是查看下.
     * 思路分析：
     * 因为不是获取，所以不能直接front++.直接front++的话，其实就相当于是取出头部数据了，比如：
     *  现在头指针指向了1.如果front ++的话，头指针指向了2了。这样就不对了。那么怎么才是查看呢？就是arr[index]这个才是查看
     *  但是，这里的index又怎么确定呢？见下分析：。
     * 又因为，front默认是从-1开始的。所以，队列头的有效数据起始位置应该是 front+1的位置。也就是index = front+1
     * @return
     */
    public int hearQueue(){
        if(isEmpty()){
            System.out.println("队列为空。不能继续获取到数据了");
            throw  new RuntimeException("队列为空");
        }
        return  arr[front+1];
    }
}
